//
//  GBInterMaster_PackUtil.m
//  NetworkTest
//
//  Created by xiaosi on 16/7/26.
//  Copyright © 2016年 xiaosi. All rights reserved.
//

#import "GBInterMaster_PackUtil.h"

@implementation GBInterMaster_PackUtil

+ (PTCP) pack10:(GBInterMaster_NetData*)data{
    int offset = 0;
    data.length = (unsigned int)data.bodyData.length + PTCP_V10_LEN_FIXED;
    if (NETBYTE_LIMIT_MAX_LENGTH < data.length) {
        return PTCP_ERR_OUT_OF_RANGE;
    }
    Byte packData[data.length];
    memset(packData, 0x00, data.length);
    packData[0] = PTCP_V10_VALUE_BEGIN_1;
    packData[1] = PTCP_V10_VALUE_BEGIN_2;
    packData[2] = PTCP_V10_VALUE_BEGIN_3;
    packData[3] = PTCP_V10_VALUE_BEGIN_4;
    offset += PTCP_V10_LEN_BEGIN_TAG;
    packData[offset] = data.dataVersion;
    offset += PTCP_V10_LEN_PROTOCAL_VER;
    packData[offset] = data.lifeCycle;
    offset += PTCP_V10_LEN_DLG_LIFE_CYCLE;
    packData[offset] = data.cmdType;
    offset += PTCP_V10_LEN_CMD_TYPE;
    packData[offset] = [ GBInterMaster_Util isChinese] ? 0 :1;
    offset += PTCP_V10_LEN_OBLIGATE1;
    packData[offset] = data.length & 0x00FF;
    packData[offset + 1] = ((data.length >> 8) & 0x00FF);
    offset += PTCP_V10_LEN_LENGTH;
    packData[offset] = data.cmd & 0x00FF;
    packData[offset + 1] = ((data.cmd >> 8) & 0x00FF);
    offset += PTCP_V10_LEN_CMD;

    long tm = (long)[[NSDate date] timeIntervalSince1970];
    packData[offset] = tm & 0x00FF;
    packData[offset + 1] = ((tm >> 8) & 0x00FF);
    packData[offset + 2] = ((tm >> 16) & 0x00FF);
    packData[offset + 3] = ((tm >> 24) & 0x00FF);
    offset += PTCP_V10_LEN_TIMESTAMP;
    packData[offset] = data.dataType & 0x00FF;
    offset += PTCP_V10_LEN_OBLIGATE2;
    packData[offset] =(data.msgId & 0x00FF);
    packData[offset + 1] = ((data.msgId >> 8) & 0x00FF);
    offset += PTCP_V10_LEN_MSG_ID;
//    if (service != null) {
//        packData[offset] = (byte) (service.get_LocalConnID() & 0x00FF);
//        packData[offset + 1] = (byte) ((service.get_LocalConnID() >> 8) & 0x00FF);
//    }
    offset += PTCP_V10_LEN_CONN_ID;
    memcpy(packData+offset, data.bodyData.bytes, data.bodyData.length);
    offset += data.bodyData.length;
    int crc16 = [GBInterMaster_APPLogic_CRC16 calcCrc16:packData withOffset:PTCP_V10_LEN_BEGIN_TAG withLen:offset - PTCP_V10_LEN_BEGIN_TAG ];
    packData[offset] = crc16 & 0x00FF;
    packData[offset + 1] = (crc16 >> 8) & 0x00FF;
    offset += PTCP_V10_LEN_CRC16;
    data.packData = [[NSData alloc] initWithBytes:packData length:data.length];
    return PTCP_OK;
}

+ (PTCP) pack10_udp:(GBInterMaster_NetData*)data{
    int offset = 0;
    data.length = (unsigned int)data.bodyData.length + PTCP_V10_LEN_FIXED - 4;
    if (NETBYTE_LIMIT_MAX_LENGTH < data.length) {
        return PTCP_ERR_OUT_OF_RANGE;
    }
    Byte packData[data.length];
    memset(packData, 0x00, data.length);
    packData[offset] = data.dataVersion;
    offset += PTCP_V10_LEN_PROTOCAL_VER;
    packData[offset] = data.lifeCycle;
    offset += PTCP_V10_LEN_DLG_LIFE_CYCLE;
    packData[offset] = data.cmdType;
    offset += PTCP_V10_LEN_CMD_TYPE;
    // packData[offset] = (byte)
    // (service.getResources().getConfiguration().locale
    // .getCountry().toUpperCase().equals("CN") ? 0 : 1);
    packData[offset] = 0x00;
    offset += PTCP_V10_LEN_OBLIGATE1;
    packData[offset] = data.length & 0x00FF;
    packData[offset + 1] = ((data.length >> 8) & 0x00FF);
    offset += PTCP_V10_LEN_LENGTH;
    packData[offset] =  data.cmd & 0x00FF;
    packData[offset + 1] = ((data.cmd>> 8) & 0x00FF);
    offset += PTCP_V10_LEN_CMD;
    long tm = (long)[[NSDate date] timeIntervalSince1970];
    packData[offset] = tm & 0x00FF;
    packData[offset + 1] = ((tm >> 8) & 0x00FF);
    packData[offset + 2] = ((tm >> 16) & 0x00FF);
    packData[offset + 3] = ((tm >> 24) & 0x00FF);
    offset += PTCP_V10_LEN_TIMESTAMP;
    packData[offset] = data.dataType & 0x00FF;
    offset += PTCP_V10_LEN_OBLIGATE2;
    packData[offset] = data.msgId & 0x00FF;
    packData[offset + 1] =  ((data.msgId >> 8) & 0x00FF);
    offset += PTCP_V10_LEN_MSG_ID;
//    if (service != null) {
//        packData[offset] = (byte) (service.get_LocalConnID() & 0x00FF);
//        packData[offset + 1] = (byte) ((service.get_LocalConnID() >> 8) & 0x00FF);
//    }
    offset += PTCP_V10_LEN_CONN_ID;
    
    memcpy(packData+offset, data.bodyData.bytes, data.bodyData.length);
    offset += data.bodyData.length;
    int crc16 = [GBInterMaster_APPLogic_CRC16 calcCrc16:packData withOffset:PTCP_V10_LEN_BEGIN_TAG withLen:offset - PTCP_V10_LEN_BEGIN_TAG ];
    packData[offset] = crc16 & 0x00FF;
    packData[offset + 1] = (crc16 >> 8) & 0x00FF;
    offset += PTCP_V10_LEN_CRC16;
    data.packData = [[NSData alloc] initWithBytes:packData length:data.length];
    return PTCP_OK;
}

+ (PTCP) unpack10:(GBInterMaster_NetData*)data outData:(NSData*)bytes{
    int offset = 0;
    unsigned long len =bytes.length;
    Byte* bys =(Byte*)[bytes bytes];
    if (len > NETBYTE_LIMIT_MAX_LENGTH) {
        return PTCP_ERR_OUT_OF_RANGE;
    }
    if (len < PTCP_V10_LEN_FIXED) {
        return PTCP_ERR_LESS_THAN_FIXED;
    }
    if (len < PTCP_V10_LEN_FIXED + 1) {
        return PTCP_ERR_INVALID_PACKAGE;
    }
    if (bys[0] !=  PTCP_V10_VALUE_BEGIN_1
        || bys[1] !=  PTCP_V10_VALUE_BEGIN_2
        || bys[2] != PTCP_V10_VALUE_BEGIN_3
        || bys[3] != PTCP_V10_VALUE_BEGIN_4) {
        return PTCP_ERR_INVALID_BEGIN_TAG;
    }
    offset += PTCP_V10_LEN_BEGIN_TAG;
    int crc1 = [GBInterMaster_APPLogic_CRC16 calcCrc16:bys withOffset:PTCP_V10_LEN_BEGIN_TAG withLen:len - PTCP_V10_LEN_CRC16 -  PTCP_V10_LEN_BEGIN_TAG];
    int crc2 = (bys[len - PTCP_V10_LEN_CRC16] & 0x00FF) + ((bys[len - PTCP_V10_LEN_CRC16 + 1] & 0x00FF) << 8 & 0xFF00);
    if (crc1 != crc2) {
        return PTCP_ERR_INVALID_CHECKVAL;
    }
    data.dataVersion = bys[offset] & 0x00FF;
    offset += PTCP_V10_LEN_PROTOCAL_VER;
    data.lifeCycle = bys[offset] & 0x00FF;
    offset += PTCP_V10_LEN_DLG_LIFE_CYCLE;
    data.cmdType = bys[offset] & 0x00FF;
    offset += PTCP_V10_LEN_CMD_TYPE;
    if (data.cmdType != PTCP_V10_VALUE_CMD_TYPE_APP_SYSTEM
        && data.cmdType != PTCP_V10_VALUE_CMD_TYPE_APP_DEVICE
        && data.cmdType != PTCP_V10_VALUE_CMD_TYPE_SERVER_PUSH) {
        return PTCP_ERR_INVALID_CMD_TYPE;
    }
    offset += PTCP_V10_LEN_OBLIGATE1;
    data.length = ((bys[offset] & 0x00FF)
                    + ((bys[offset + 1] & 0x00FF) << 8 & 0xFF00));
    offset += PTCP_V10_LEN_LENGTH;
    data.cmd = (int)((bys[offset] & 0x00FF)  + ((bys[offset + 1] & 0x00FF) << 8 & 0xFF00));
    offset += PTCP_V10_LEN_CMD;
    long tm = (long)((bys[offset] & 0x00FF)  + ((bys[offset + 1] & 0x00FF) << 8 & 0xFF00)+ ((bys[offset + 2] & 0x0000FF) << 16 & 0xFF0000)+ ((bys[offset + 3] & 0x000000FF) << 24 & 0xFF000000));
    data.tStamp = tm;
    offset += PTCP_V10_LEN_TIMESTAMP;
    offset += PTCP_V10_LEN_OBLIGATE2;
    data.msgId = (int)((bys[offset] & 0x00FF) + ((bys[offset + 1] & 0x00FF) << 8 & 0xFF00));
    offset += PTCP_V10_LEN_MSG_ID;
    data.connId = (int)((bys[offset] & 0x00FF) + ((bys[offset + 1] & 0x00FF) << 8 & 0xFF00));
    offset += PTCP_V10_LEN_CONN_ID;
    int bodyLen = len - PTCP_V10_LEN_FIXED;
    Byte bodyData[bodyLen];
    memset(bodyData, 0x00, bodyLen);
    memcpy(bodyData, bys + offset, bodyLen);
    data.bodyData = [[NSData alloc] initWithBytes:bodyData length:bodyLen];
    return PTCP_OK;
}

@end
